30行くらいで作るはじめてのインフラ構築
弊社には 7月7日の会社のお誕生日にブログ書くという文化があります。 せっかくなので私も最近はまっている CDK ネタで一本書いてみようと思います。
ついこの間、はじめて CDK を使って VPC 環境を構築する機会があったのですが、思いのほかシンプルだったのでご紹介したいと思います。
作るもの
VPC、 ECS、 Fargateでインフラ環境を構築します。
使うもの
AWS CDK を Typescript で記述します。
cdk --version 1.32.2 tsc -v Version 3.7.4
Typescript の watch モードをオンにする
私はよくビルドし忘れてデプロイの時にこけるので Watch モードをオンにして作業します。
tsc -w
これで記述したそばから Typescript コンパイラがプロジェクトをビルドしながらエラーを見つけてくれるので早い段階でエラーにも気づくことができます。
Step1: cdk init
空のディレクトリを作成し、cdk init
します。
touch cdk cd cdk cdk init --language typescript
Step2: VPC を作る
lib/
配下のcdk-stack.ts
ファイルを編集していきます。
まずは VPC を作成しましょう。
import * as cdk from "@aws-cdk/core"; import { Vpc } from "@aws-cdk/aws-ec2"; export class CdkStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = new Vpc(this, "sample-vpc", {}); } }
上のコードをデプロイすると何ができるか見てみましょう。 たった 1 行しか書いてないのになんだかたくさんリソースができてますね。すごい!
マネジメントコンソールで CloudFormation を開いて CloudFormation Designer を開いてみましょう。
作成されたリソースはざっと以下でした。
- VPC
- Public Subnet x2
- Private Subnet x2
- NatGateway x2
- Elastic IP x2
- Internet Gateway
- Route Table x4
細かい各デフォルトの値はこちらのドキュメントを参考にしてください。
何も指定しないと、上記の内容の VPC 環境が作成されます。ここに例えば、マルチ AZ 設定を 2 から 3 へ増やしたい、NatGateway の数を 1 つに減らしたい、Isolated Subnet も追加したい、などの細かい設定を追加してゆきます。
今回はこのままの設定で次に進みます。
Step2: ECS クラスタを追加
ECS を追加します。Propsには先ほど作成したVPCを渡します。
lib/cdk-stack.ts
const cluster = new Cluster(this, "ecs-cluster", { vpc, });
Step3: ALB を追加する
最後に ALB を追加して、サンプルのamazon/amazon-ecs-sample
image にアクセスできるようにしてみましょう。@aws-cdk/aws-ecs-patterns
を使って ALB を追加します。
今回は Fargate を利用します。Version は指定がないとlatest
になるためplatformVersion
を指定します。
lib/cdk-stack.ts
const loadBalancedFargateService = new ApplicationLoadBalancedFargateService( this, "fargate-alb-service", { cluster, taskImageOptions: { image: ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, platformVersion: FargatePlatformVersion.VERSION1_3, } ); }
動作確認
最後に再度デプロイして、ALBのDNSnameから、デプロイしたコンテナへアクセスしてみましょう。
このようにサンプルのPHPAppが表示されれば成功です!
CDK全文
全文はこんな感じになりました。 記述した部分のコードだけを見れば20行程でしょうか。
import * as cdk from "@aws-cdk/core"; import { Vpc } from "@aws-cdk/aws-ec2"; import { ApplicationLoadBalancedFargateService } from "@aws-cdk/aws-ecs-patterns"; import { ContainerImage, Cluster, FargatePlatformVersion, } from "@aws-cdk/aws-ecs"; export class CdkStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // Create VPC const vpc = new Vpc(this, "sample-vpc", {}); // Create ECS Cluster const cluster = new Cluster(this, "ecs-cluster", { vpc, }); // Create ALB const loadBalancedFargateService = new ApplicationLoadBalancedFargateService( this, "fargate-alb-service", { cluster, taskImageOptions: { image: ContainerImage.fromRegistry("amazon/amazon-ecs-sample"), }, platformVersion: FargatePlatformVersion.VERSION1_3, } ); } }
因みに上記のコードで生成されたCloudFormation(json)は830行でした。
Step4: cdk destroy
不要な高額請求を避けるため、忘れずにcdk destroy
を実行しましょう。
あとがき
少し前までは頑張って記述していた大量のCloudFormationがこれだけ少量のコードで再現できるのは本当に素晴らしいです。
細かく指定をしなくてもいい感じに必要なリソースを作成してくれるのはCDKの便利ポイントの一つです。しかし、少量のコードで済んでしまうぶん何のリソースを作成しているのかがコードから読み取りづらくなってしまうこともあります。
コードの変更を検知するためのテストを書いたり、構成図などをドキュメントに残したりする等、CDKの強みを生かして開発をスムーズに進められるようにするには少し工夫があるといいかもしれません。
この記事が誰かの参考になれば嬉しいです。